home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume89
/
languags
/
motoasem.1
< prev
next >
Wrap
Text File
|
1989-03-15
|
52KB
|
2,375 lines
Path: xanth!nic.MR.NET!hal!cwjcc!mailrus!ulowell!page
From: page@swan.ulowell.edu (Bob Page)
Newsgroups: comp.sources.amiga
Subject: v89i055: moto-assem - m68k assember from motorola's bbs, Part01/02
Message-ID: <12237@swan.ulowell.edu>
Date: 15 Mar 89 18:39:37 GMT
Organization: University of Lowell, Computer Science Dept.
Lines: 2364
Approved: page@swan.ulowell.edu
Submitted-by: gmg@hcx.uucp (Greg Garner)
Posting-number: Volume 89, Issue 55
Archive-name: langauges/moto-assem.1
These files came from the Motorola Freeware BBS. Their BBS now has an
amiga upload/download section (YEA!). I obtained explicit permission
to post these to comp.sources.amiga and also to give these files to
Fred Dish for inclusion in one of his disks.
# This is a shell archive.
# Remove everything above and including the cut line.
# Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# AS.C
# AS.H
# AS0.C
# AS1.C
# AS11.C
# AS4.C
# AS5.C
# AS9.C
# DO0.C
# DO1.C
# DO11.C
# DO4.C
# DO5.C
# DO9.C
# FFWD.C
# OUTPUT.C
# PSEUDO.C
# This archive created: Wed Mar 15 13:33:52 1989
cat << \SHAR_EOF > AS.C
char mapdn();
char *alloc();
/*
* as --- cross assembler main program
*/
main(argc,argv)
int argc;
char **argv;
{
char **np;
char *i;
FILE *fopen();
int j = 0;
if(argc < 2){
printf("Usage: %s [files]\n",argv[j]);
exit(1);
}
Argv = argv;
initialize();
while ((*argv[j] != '-') && (j<argc))
j++;
N_files = j-1;
if (j < argc )
{
argv[j]++;
while (j<argc)
{
for (i = argv[j]; *i != 0; i++)
if ((*i <= 'Z') && (*i >= 'A'))
*i = *i + 32;
if (strcmp(argv[j],"l")==0)
Lflag = 1;
else if (strcmp(argv[j],"nol")==0)
Lflag = 0;
else if (strcmp(argv[j],"c")==0)
Cflag = 1;
else if (strcmp(argv[j],"noc")==0)
Cflag = 0;
else if (strcmp(argv[j],"s")==0)
Sflag = 1;
else if (strcmp(argv[j],"cre")==0)
CREflag = 1;
j++;
}
}
root = NULL;
Cfn = 0;
np = argv;
Line_num = 0; /* reset line number */
while( ++Cfn <= N_files )
if((Fd = fopen(*++np,"r")) == NULL)
printf("as: can't open %s\n",*np);
else{
make_pass();
fclose(Fd);
}
if( Err_count == 0 ){
Pass++;
re_init();
Cfn = 0;
np = argv;
Line_num = 0;
while( ++Cfn <= N_files)
if((Fd = fopen(*++np,"r")) != NULL)
{
make_pass();
fclose(Fd);
}
if (Sflag == 1)
{
printf ("\f");
stable (root);
}
if (CREflag == 1)
{
printf ("\f");
cross (root);
}
fprintf(Objfil,"S9030000FC\r\n"); /* at least give a decent ending */
}
exit(Err_count);
}
initialize()
{
FILE *fopen();
int i = 0;
#ifdef DEBUG
printf("Initializing\n");
#endif
Err_count = 0;
Pc = 0;
Pass = 1;
Lflag = 0;
Cflag = 0;
Ctotal = 0;
Sflag = 0;
CREflag = 0;
N_page = 0;
Line[MAXBUF-1] = NEWLINE;
strcpy(Obj_name,Argv[1]); /* copy first file name into array */
do {
if (Obj_name[i]=='.')
Obj_name[i]=0;
}
while (Obj_name[i++] != 0);
strcat(Obj_name,".s19"); /* append .out to file name. */
if( (Objfil = fopen(Obj_name,"w")) == NULL)
fatal("Can't create object file");
fwdinit(); /* forward ref init */
localinit(); /* target machine specific init. */
}
re_init()
{
#ifdef DEBUG
printf("Reinitializing\n");
#endif
Pc = 0;
E_total = 0;
P_total = 0;
Ctotal = 0;
N_page = 0;
fwdreinit();
}
make_pass()
{
char *fgets();
#ifdef DEBUG
printf("Pass %d\n",Pass);
#endif
while( fgets(Line,MAXBUF-1,Fd) != (char *)NULL ){
Line_num++;
P_force = 0; /* No force unless bytes emitted */
N_page = 0;
if(parse_line())
process();
if(Pass == 2 && Lflag && !N_page)
print_line();
P_total = 0; /* reset byte count */
Cycles = 0; /* and per instruction cycle count */
}
f_record();
}
/*
* parse_line --- split input line into label, op and operand
*/
parse_line()
{
register char *ptrfrm = Line;
register char *ptrto = Label;
char *skip_white();
if( *ptrfrm == '*' || *ptrfrm == '\n' )
return(0); /* a comment line */
while( delim(*ptrfrm)== NO )
*ptrto++ = *ptrfrm++;
if(*--ptrto != ':')ptrto++; /* allow trailing : */
*ptrto = EOS;
ptrfrm = skip_white(ptrfrm);
ptrto = Op;
while( delim(*ptrfrm) == NO)
*ptrto++ = mapdn(*ptrfrm++);
*ptrto = EOS;
ptrfrm = skip_white(ptrfrm);
ptrto = Operand;
while( *ptrfrm != NEWLINE )
*ptrto++ = *ptrfrm++;
*ptrto = EOS;
#ifdef DEBUG
printf("Label-%s-\n",Label);
printf("Op----%s-\n",Op);
printf("Operand-%s-\n",Operand);
#endif
return(1);
}
/*
* process --- determine mnemonic class and act on it
*/
process()
{
register struct oper *i;
struct oper *mne_look();
Old_pc = Pc; /* setup `old' program counter */
Optr = Operand; /* point to beginning of operand field */
if(*Op==EOS){ /* no mnemonic */
if(*Label != EOS)
install(Label,Pc);
}
else if( (i = mne_look(Op))== NULL)
error("Unrecognized Mnemonic");
else if( i->class == PSEUDO )
do_pseudo(i->opcode);
else{
if( *Label )install(Label,Pc);
if(Cflag)Cycles = i->cycles;
do_op(i->opcode,i->class);
if(Cflag)Ctotal += Cycles;
}
}
SHAR_EOF
cat << \SHAR_EOF > AS.H
/*
* machine independent definitions and global variables
*/
#define YES 1
#define NO 0
#define ERR (-1)
#define MAXBUF 128
#define MAXOP 10 /* longest mnemonic */
#define MAXLAB 16
#define E_LIMIT 32
#define P_LIMIT 64
/* Character Constants */
#define NEWLINE '\n'
#define TAB '\t'
#define BLANK ' '
#define EOS '\0'
/* Opcode Classes */
#define INH 0 /* Inherent */
#define GEN 1 /* General Addressing */
#define IMM 2 /* Immediate only */
#define REL 3 /* Short Relative */
#define P2REL 4 /* Long Relative */
#define P1REL 5 /* Long Relative (LBRA and LBSR)*/
#define NOIMM 6 /* General except for Immediate */
#define P2GEN 7 /* Page 2 General */
#define P3GEN 8 /* Page 3 General */
#define RTOR 9 /* Register To Register */
#define INDEXED 10 /* Indexed only */
#define RLIST 11 /* Register List */
#define P2NOIMM 12 /* Page 2 No Immediate */
#define P2INH 13 /* Page 2 Inherent */
#define P3INH 14 /* Page 3 Inherent */
#define GRP2 15 /* Group 2 (Read/Modify/Write) */
#define LONGIMM 16 /* Immediate mode takes 2 bytes */
#define BTB 17 /* Bit test and branch */
#define SETCLR 18 /* Bit set or clear */
#define CPD 19 /* compare d 6811 */
#define XLIMM 20 /* LONGIMM for X 6811 */
#define XNOIMM 21 /* NOIMM for X 6811 */
#define YLIMM 22 /* LONGIMM for Y 6811 */
#define YNOIMM 23 /* NOIMM for Y 6811 */
#define FAKE 24 /* convenience mnemonics 6804 */
#define APOST 25 /* A accum after opcode 6804 */
#define BPM 26 /* branch reg plus/minus 6804 */
#define CLRX 27 /* mvi x,0 6804 */
#define CLRY 28 /* mvi y,0 6804 */
#define LDX 29 /* mvi x,expr 6804 */
#define LDY 30 /* mvi y,expr 6804 */
#define MVI 31 /* mvi 6804 */
#define EXT 32 /* extended 6804 */
#define BIT 33 /* bit manipulation 6301 */
#define SYS 34 /* syscalls (really swi) */
#define PSEUDO 35 /* Pseudo ops */
/* global variables */
int Line_num =0; /* current line number */
int Err_count =0; /* total number of errors */
char Line[MAXBUF] = {0}; /* input line buffer */
char Label[MAXLAB] = {0}; /* label on current line */
char Op[MAXOP] = {0}; /* opcode mnemonic on current line */
char Operand[MAXBUF] = {0}; /* remainder of line after op */
char *Optr =0; /* pointer into current Operand field */
int Result =0; /* result of expression evaluation */
int Force_word =0; /* Result should be a word when set */
int Force_byte =0; /* Result should be a byte when set */
int Pc =0; /* Program Counter */
int Old_pc =0; /* Program Counter at beginning */
int Last_sym =0; /* result of last lookup */
int Pass =0; /* Current pass # */
int N_files =0; /* Number of files to assemble */
FILE *Fd =0; /* Current input file structure */
int Cfn =0; /* Current file number 1...n */
int Ffn =0; /* forward ref file # */
int F_ref =0; /* next line with forward ref */
char **Argv =0; /* pointer to file names */
int E_total =0; /* total # bytes for one line */
int E_bytes[E_LIMIT] = {0}; /* Emitted held bytes */
int E_pc =0; /* Pc at beginning of collection*/
int Lflag = 0; /* listing flag 0=nolist, 1=list*/
int P_force = 0; /* force listing line to include Old_pc */
int P_total =0; /* current number of bytes collected */
int P_bytes[P_LIMIT] = {0}; /* Bytes collected for listing */
int Cflag = 0; /* cycle count flag */
int Cycles = 0; /* # of cycles per instruction */
long Ctotal = 0; /* # of cycles seen so far */
int Sflag = 0; /* symbol table flag, 0=no symbol */
int N_page = 0; /* new page flag */
int Page_num = 2; /* page number */
int CREflag = 0; /* cross reference table flag */
struct link { /* linked list to hold line numbers */
int L_num; /* line number */
struct link *next; /* pointer to next node */
};
struct nlist { /* basic symbol table entry */
char *name;
int def;
struct nlist *Lnext ; /* left node of the tree leaf */
struct nlist *Rnext; /* right node of the tree leaf */
struct link *L_list; /* pointer to linked list of line numbers */
};
struct oper { /* an entry in the mnemonic table */
char *mnemonic; /* its name */
char class; /* its class */
int opcode; /* its base opcode */
char cycles; /* its base # of cycles */
};
struct nlist *root; /* root node of the tree */
FILE *Objfil =0; /* object file's file descriptor*/
char Obj_name[] = {" "};
SHAR_EOF
cat << \SHAR_EOF > AS0.C
#include <stdio.h>
#include "as.h"
#include "table0.h"
#include "as.c"
#include "do0.c"
#include "pseudo.c"
#include "eval.c"
#include "symtab.c"
#include "util.c"
#include "ffwd.c"
#include "output.c"
SHAR_EOF
cat << \SHAR_EOF > AS1.C
#include <stdio.h>
#include "as.h"
#include "table1.h"
#include "as.c"
#include "do1.c"
#include "pseudo.c"
#include "eval.c"
#include "symtab.c"
#include "util.c"
#include "ffwd.c"
#include "output.c"
SHAR_EOF
cat << \SHAR_EOF > AS11.C
#include <stdio.h>
#include "as.h"
#include "table11.h"
#include "as.c"
#include "do11.c"
#include "pseudo.c"
#include "eval.c"
#include "symtab.c"
#include "util.c"
#include "ffwd.c"
#include "output.c"
SHAR_EOF
cat << \SHAR_EOF > AS4.C
#include <stdio.h>
#include "as.h"
#include "table4.h"
#include "as.c"
#include "do4.c"
#include "pseudo.c"
#include "eval.c"
#include "symtab.c"
#include "util.c"
#include "ffwd.c"
#include "output.c"
SHAR_EOF
cat << \SHAR_EOF > AS5.C
#include <stdio.h>
#include "as.h"
#include "table5.h"
#include "as.c"
#include "do5.c"
#include "pseudo.c"
#include "eval.c"
#include "symtab.c"
#include "util.c"
#include "ffwd.c"
#include "output.c"
SHAR_EOF
cat << \SHAR_EOF > AS9.C
#include <stdio.h>
#include "as.h"
#include "table9.h"
#include "as.c"
#include "do9.c"
#include "pseudo.c"
#include "eval.c"
#include "symtab.c"
#include "util.c"
#include "ffwd.c"
#include "output.c"
SHAR_EOF
cat << \SHAR_EOF > DO0.C
/*
* MC6800/02 specific processing
*/
/* addressing modes */
#define IMMED 0 /* immediate */
#define IND 1 /* indexed */
#define OTHER 2 /* NOTA */
/*
* localinit --- machine specific initialization
*/
localinit()
{
}
/*
* do_op --- process mnemonic
*
* Called with the base opcode and it's class. Optr points to
* the beginning of the operand field.
*/
do_op(opcode,class)
int opcode; /* base opcode */
int class; /* mnemonic class */
{
int dist; /* relative branch distance */
int amode; /* indicated addressing mode */
char *peek;
/* guess at addressing mode */
peek = Optr;
amode = OTHER;
while( !delim(*peek) && *peek != EOS) /* check for comma in operand field */
if( *peek++ == ',' ){
amode = IND;
break;
}
if( *Optr == '#' ) amode = IMMED;
switch(class){
case INH: /* inherent addressing */
emit(opcode);
return;
case GEN: /* general addressing */
do_gen(opcode,amode);
return;
case REL: /* relative branches */
eval();
dist = Result - (Pc+2);
emit(opcode);
if( (dist >127 || dist <-128) && Pass==2){
error("Branch out of Range");
emit(lobyte(-2));
return;
}
emit(lobyte(dist));
return;
case NOIMM:
if( amode == IMMED){
error("Immediate Addressing Illegal");
return;
}
if((opcode == 0x8D) && (amode == IND)){
Cycles-=2;
}
do_gen(opcode,amode);
return;
case LONGIMM:
if( amode == IMMED ){
emit(opcode);
Optr++;
eval();
eword(Result);
return;
}
do_gen(opcode,amode);
return;
case GRP2:
if( amode == IND ){
Cycles++;
do_indexed(opcode);
return;
}
/* extended addressing */
eval();
emit(opcode+0x10);
eword(Result);
return;
default:
fatal("Error in Mnemonic table");
}
}
/*
* do_gen --- process general addressing modes
*/
do_gen(op,mode)
int op;
int mode;
{
if( mode == IMMED){
Optr++;
emit(op);
eval();
emit(lobyte(Result));
return;
}
else if( mode == IND ){
Cycles+=3;
do_indexed(op+0x20);
return;
}
else if( mode == OTHER){
eval();
if(Force_word){
emit(op+0x30);
eword(Result);
Cycles+=2;
return;
}
if(Force_byte){
emit(op+0x10);
emit(lobyte(Result));
Cycles++;
return;
}
if(Result>=0 && Result <=0xFF){
emit(op+0x10);
emit(lobyte(Result));
Cycles++;
return;
}
else {
emit(op+0x30);
eword(Result);
Cycles+=2;
return;
}
}
else {
error("Unknown Addressing Mode");
return;
}
}
/*
* do_indexed --- handle all wierd stuff for indexed addressing
*/
do_indexed(op)
int op;
{
emit(op);
eval();
if( mapdn(*++Optr) != 'x' )
warn("Indexed Addressing Assumed");
if( Result < 0 || Result > 255)
warn("Value Truncated");
emit(lobyte(Result));
}
SHAR_EOF
cat << \SHAR_EOF > DO1.C
/*
* MC6801 specific processing
*/
/* addressing modes */
#define IMMED 0 /* immediate */
#define IND 1 /* indexed */
#define OTHER 2 /* NOTA */
/*
* localinit --- machine specific initialization
*/
localinit()
{
}
/*
* do_op --- process mnemonic
*
* Called with the base opcode and it's class. Optr points to
* the beginning of the operand field.
*/
do_op(opcode,class)
int opcode; /* base opcode */
int class; /* mnemonic class */
{
int dist; /* relative branch distance */
int amode; /* indicated addressing mode */
char *peek;
/* guess at addressing mode */
peek = Optr;
amode = OTHER;
while( !delim(*peek) && *peek != EOS) /* check for comma in operand field */
if( *peek++ == ',' ){
amode = IND;
break;
}
if( *Optr == '#' ) amode = IMMED;
switch(class){
case INH: /* inherent addressing */
emit(opcode);
return;
case GEN: /* general addressing */
do_gen(opcode,amode);
return;
case REL: /* relative branches */
eval();
dist = Result - (Pc+2);
emit(opcode);
if( (dist >127 || dist <-128) && Pass==2){
error("Branch out of Range");
emit(lobyte(-2));
return;
}
emit(lobyte(dist));
return;
case NOIMM:
if( amode == IMMED){
error("Immediate Addressing Illegal");
return;
}
do_gen(opcode,amode);
return;
case LONGIMM:
if( amode == IMMED ){
emit(opcode);
Optr++;
eval();
eword(Result);
return;
}
do_gen(opcode,amode);
return;
case GRP2:
if( amode == IND ){
do_indexed(opcode);
return;
}
/* extended addressing */
eval();
emit(opcode+0x10);
eword(Result);
return;
default:
fatal("Error in Mnemonic table");
}
}
/*
* do_gen --- process general addressing modes
*/
do_gen(op,mode)
int op;
int mode;
{
if( mode == IMMED){
Optr++;
emit(op);
eval();
emit(lobyte(Result));
return;
}
else if( mode == IND ){
Cycles+=2;
do_indexed(op+0x20);
return;
}
else if( mode == OTHER){
eval();
if(Force_word){
emit(op+0x30);
eword(Result);
Cycles+=2;
return;
}
if(Force_byte){
emit(op+0x10);
emit(lobyte(Result));
Cycles++;
return;
}
if(Result>=0 && Result <=0xFF){
emit(op+0x10);
emit(lobyte(Result));
Cycles++;
return;
}
else {
emit(op+0x30);
eword(Result);
Cycles+=2;
return;
}
}
else {
error("Unknown Addressing Mode");
return;
}
}
/*
* do_indexed --- handle all wierd stuff for indexed addressing
*/
do_indexed(op)
int op;
{
emit(op);
eval();
if( mapdn(*++Optr) != 'x' )
warn("Indexed Addressing Assumed");
if( Result < 0 || Result > 255)
warn("Value Truncated");
emit(lobyte(Result));
}
SHAR_EOF
cat << \SHAR_EOF > DO11.C
/*
* MC68HC11 specific processing
*/
#define PAGE1 0x00
#define PAGE2 0x18
#define PAGE3 0x1A
#define PAGE4 0xCD
/* addressing modes */
#define IMMED 0
#define INDX 1
#define INDY 2
#define LIMMED 3 /* long immediate */
#define OTHER 4
int yflag = 0; /* YNOIMM, YLIMM, and CPD flag */
/*
* localinit --- machine specific initialization
*/
localinit()
{
}
/*
* do_op --- process mnemonic
*
* Called with the base opcode and it's class. Optr points to
* the beginning of the operand field.
*/
do_op(opcode,class)
int opcode; /* base opcode */
int class; /* mnemonic class */
{
int dist; /* relative branch distance */
int amode; /* indicated addressing mode */
char *peek;
/* guess at addressing mode */
peek = Optr;
amode = OTHER;
while( !delim(*peek) && *peek != EOS) /* check for comma in operand field */
if( *peek++ == ',' ){
if( mapdn(*peek) == 'y' )
amode = INDY;
else
amode = INDX;
break;
}
if( *Optr == '#' ) amode = IMMED;
yflag = 0;
switch(class){
case P2INH:
emit(PAGE2);
case INH: /* inherent addressing */
emit(opcode);
return;
case REL: /* relative branches */
eval();
dist = Result - (Pc+2);
emit(opcode);
if( (dist >127 || dist <-128) && Pass==2){
error("Branch out of Range");
emit(lobyte(-2));
return;
}
emit(lobyte(dist));
return;
case LONGIMM:
if( amode == IMMED )
amode = LIMMED;
case NOIMM:
if( amode == IMMED ){
error("Immediate Addressing Illegal");
return;
}
case GEN: /* general addressing */
do_gen(opcode,amode,PAGE1,PAGE1,PAGE2);
return;
case GRP2:
if( amode == INDY ){
Cycles++;
emit(PAGE2);
amode = INDX;
}
if( amode == INDX )
do_indexed(opcode);
else{ /* extended addressing */
eval();
emit(opcode+0x10);
eword(Result);
}
return;
case CPD: /* cmpd */
if( amode == IMMED )
amode = LIMMED;
if( amode == INDY )
yflag=1;
do_gen(opcode,amode,PAGE3,PAGE3,PAGE4);
return;
case XNOIMM: /* stx */
if( amode == IMMED ){
error("Immediate Addressing Illegal");
return;
}
case XLIMM: /* cpx, ldx */
if( amode == IMMED )
amode = LIMMED;
do_gen(opcode,amode,PAGE1,PAGE1,PAGE4);
return;
case YNOIMM: /* sty */
if( amode == IMMED ){
error("Immediate Addressing Illegal");
return;
}
case YLIMM: /* cpy, ldy */
if(amode == INDY)
yflag=1;
if( amode == IMMED )
amode = LIMMED;
do_gen(opcode,amode,PAGE2,PAGE3,PAGE2);
return;
case BTB: /* bset, bclr */
case SETCLR: /* brset, brclr */
opcode = bitop(opcode,amode,class);
if (amode == INDX)
Cycles++;
if( amode == INDY ){
Cycles+=2;
emit(PAGE2);
amode = INDX;
}
emit(opcode);
eval();
emit(lobyte(Result)); /* address */
if( amode == INDX )
Optr += 2; /* skip ,x or ,y */
Optr = skip_white(Optr);
eval();
emit(lobyte(Result)); /* mask */
if( class == SETCLR )
return;
Optr = skip_white(Optr);
eval();
dist = Result - (Pc+1);
if( (dist >127 || dist <-128) && Pass==2){
error("Branch out of Range");
dist = Old_pc - (Pc+1);
}
emit(lobyte(dist));
return;
default:
fatal("Error in Mnemonic table");
}
}
/*
* bitop --- adjust opcode on bit manipulation instructions
*/
bitop(op,mode,class)
int op;
int mode;
int class;
{
if( mode == INDX || mode == INDY )
return(op);
if( class == SETCLR )
return(op-8);
else if(class==BTB)
return(op-12);
else
fatal("bitop");
}
/*
* do_gen --- process general addressing modes
*/
do_gen(op,mode,pnorm,px,py)
int op; /* base opcode */
int mode; /* addressing mode */
int pnorm; /* page for normal addressing modes: IMM,DIR,EXT */
int px; /* page for INDX addressing */
int py; /* page for INDY addressing */
{
switch(mode){
case LIMMED:
Optr++;
epage(pnorm);
emit(op);
eval();
eword(Result);
break;
case IMMED:
Optr++;
epage(pnorm);
emit(op);
eval();
emit(lobyte(Result));
break;
case INDY:
if(yflag)
Cycles += 2;
else
Cycles += 3;
epage(py);
do_indexed(op+0x20);
break;
case INDX:
Cycles+=2;
epage(px);
do_indexed(op+0x20);
break;
case OTHER:
eval();
epage(pnorm);
if(Force_word){
emit(op+0x30);
eword(Result);
Cycles+=2;
break;
}
if(Force_byte){
emit(op+0x10);
emit(lobyte(Result));
Cycles++;
break;
}
if(Result>=0 && Result <=0xFF){
emit(op+0x10);
emit(lobyte(Result));
Cycles++;
break;
}
else {
emit(op+0x30);
eword(Result);
Cycles+=2;
break;
}
break;
default:
error("Unknown Addressing Mode");
}
}
/*
* do_indexed --- handle all wierd stuff for indexed addressing
*/
do_indexed(op)
int op;
{
char c;
emit(op);
eval();
if( *Optr++ != ',' )
error("Syntax");
c = mapdn(*Optr++);
if( c != 'x' && c != 'y')
warn("Indexed Addressing Assumed");
if( Result < 0 || Result > 255)
warn("Value Truncated");
emit(lobyte(Result));
}
/*
* epage --- emit page prebyte
*/
epage(p)
int p;
{
if( p != PAGE1 ) /* PAGE1 means no prebyte */
emit(p);
}
SHAR_EOF
cat << \SHAR_EOF > DO4.C
/*
* MC6804 specific processing
*/
#define IMMED 0
#define IND 1
#define OTHER 2
/* special addresses */
#define XREG 0x80
#define YREG 0x81
#define SD1REG 0x82
#define SD2REG 0x83
#define ACCUM 0xFF
/*
* localinit --- machine specific initialization
*/
localinit()
{
install("x",XREG);
install("X",XREG);
install("y",YREG);
install("Y",YREG);
install("a",ACCUM);
install("A",ACCUM);
}
/*
* do_op --- process mnemonic
*/
do_op(opcode,class)
{
int dist; /* relative branch distance */
int amode; /* indicated addressing mode */
int r1; /* first eval() for mvi */
if (( *Operand == '[' ) || ( *Operand == ','))
amode = IND;
else if( *Operand == '#' )
amode = IMMED;
else
amode = OTHER;
switch(class){
case INH: /* inherent addressing */
emit(opcode);
return;
case APOST: /* A address in mem follows opcode */
emit(opcode);
emit(ACCUM);
return;
case REL: /* short relative branches */
eval();
dist = Result - (Pc+1);
if( (dist >15 || dist <-16) && Pass==2){
error("Branch out of Range");
dist = -1;
}
emit(opcode + (dist&0x1F));
return;
case BTB:
case SETCLR:
eval();
if(Result <0 || Result >7){
error("Bit Number must be 0-7");
return;
}
emit( opcode + Result);
if(*Optr++ != ',')error("SYNTAX");
eval();
emit(lobyte(Result));
if( class == SETCLR )
return;
if(*Optr++ != ',')error("SYNTAX");
eval();
dist = Result - (Old_pc+3);
if( (dist >127 || dist <-128) && Pass==2){
error("Branch out of Range");
dist = -3;
return;
}
emit(lobyte(dist));
return;
case EXT: /* jsr, jmp */
eval();
emit(opcode | (hibyte(Result) & 0x0F));
emit(lobyte(Result));
return;
case BPM: /* brset/clr 7,accum,target */
emit(opcode);
emit(ACCUM);
eval();
dist = Result - (Old_pc + 3);
if ((dist > 127 || dist < -128) && Pass == 2) {
error("Branch out of range");
dist = -3;
return;
}
emit(lobyte(dist));
return;
case MVI:
eval();
r1 = Result; /* save result */
if (*Optr++ != ',')
warn("Missing ','");
eval();
mvi(opcode,r1,Result);
return;
case CLRX: /* mvi xreg,0 */
mvi(opcode,XREG,0);
return;
case CLRY: /* mvi yreg,0 */
mvi(opcode,YREG,0);
return;
case LDX: /* mvi xreg data */
if (amode == IMMED) Optr++;
eval();
mvi(opcode,XREG,Result);
return;
case LDY: /* mvi yreg data */
if (amode == IMMED) Optr++;
eval();
mvi(opcode,YREG,Result);
return;
case NOIMM:
if( amode == IMMED ){
error("Immediate Addressing Illegal");
return;
}
case GEN:
if ( amode == IMMED ) {
Optr++;
eval();
emit(opcode | 0x08);
emit(Result);
return;
}
if( amode == IND ){
Optr++;
eval();
if ((*Optr != ']') && (*Operand != ','))
warn("Missing ']'");
if (Result != XREG && Result != YREG) {
error("Operand must be $80 or $81");
emit(opcode);
return;
}
emit(opcode | ((Result&0x01)<<4));
return;
}
eval();
if (XREG <= Result && Result <=SD2REG){
/*check for short direct cases*/
if ( opcode==0xE6 ) { /* inc */
emit(0xA8 + (Result-XREG));
return;
}
if ( opcode==0xE7 ) { /* dec */
emit(0xB8 + (Result-XREG));
return;
}
if ( opcode==0xE0 ) { /* lda */
emit(0xAC | (Result-XREG));
return;
}
if ( opcode==0xE1 ) { /* sta */
emit(0xBC | (Result-XREG));
return;
}
}
/* else direct addressing */
emit( opcode | 0x18);
emit(lobyte(Result));
return;
default:
fatal("Error in Mnemonic table");
}
}
mvi(op,to,from)
int op,to,from;
{
emit(op);
emit(to);
emit(from);
}
SHAR_EOF
cat << \SHAR_EOF > DO5.C
/*
* MC6805 specific processing
*/
/* addressing modes */
#define IMMED 0 /* immediate */
#define IND 1 /* indexed */
#define OTHER 2 /* NOTA */
/*
* localinit --- machine specific initialization
*/
localinit()
{
}
/*
* do_op --- process mnemonic
*
* Called with the base opcode and it's class. Optr points to
* the beginning of the operand field.
*/
do_op(opcode,class)
int opcode; /* base opcode */
int class; /* mnemonic class */
{
int dist; /* relative branch distance */
int amode; /* indicated addressing mode */
char *peek;
/* guess at addressing mode */
peek = Optr;
amode = OTHER;
while( !delim(*peek) && *peek != EOS) /* check for comma in operand field */
if( *peek++ == ',' ){
amode = IND;
break;
}
if( *Optr == '#' ) amode = IMMED;
switch(class){
case INH: /* inherent addressing */
emit(opcode);
return;
case GEN: /* general addressing */
do_gen(opcode,amode);
return;
case REL: /* short relative branches */
eval();
dist = Result - (Pc+2);
emit(opcode);
if( (dist >127 || dist <-128) && Pass==2){
error("Branch out of Range");
emit(lobyte(-2));
return;
}
emit(lobyte(dist));
return;
case NOIMM:
if( amode == IMMED ){
error("Immediate Addressing Illegal");
return;
}
do_gen(opcode,amode);
return;
case GRP2:
if( amode == IND ){
do_indexed(opcode+0x20);
return;
}
eval();
Cycles += 2;
if(Force_byte){
emit(opcode);
emit(lobyte(Result));
return;
}
if(Result>=0 && Result <=0xFF){
emit(opcode);
emit(lobyte(Result));
return;
}
error("Extended Addressing not allowed");
return;
case SETCLR:
case BTB:
eval();
if(Result <0 || Result >7){
error("Bit Number must be 0-7");
return;
}
emit( opcode | (Result << 1));
if(*Optr++ != ',')error("SYNTAX");
eval();
emit(lobyte(Result));
if(class==SETCLR)
return;
/* else it's bit test and branch */
if(*Optr++ != ',')error("SYNTAX");
eval();
dist = Result - (Old_pc+3);
if( (dist >127 || dist <-128) && Pass==2){
error("Branch out of Range");
emit(lobyte(-3));
return;
}
emit(lobyte(dist));
return;
default:
fatal("Error in Mnemonic table");
}
}
/*
* do_gen --- process general addressing
*/
do_gen(op,mode)
int op;
int mode;
{
if( mode == IMMED){
Optr++;
emit(op);
eval();
emit(lobyte(Result));
return;
}
else if( mode == IND ){
do_indexed(op+0x30);
return;
}
else if( mode == OTHER){ /* direct or extended addressing */
eval();
if(Force_word){
emit(op+0x20);
eword(Result);
Cycles += 3;
return;
}
if(Force_byte){
emit(op+0x10);
emit(lobyte(Result));
Cycles += 2;
return;
}
if(Result >= 0 && Result <= 0xFF){
emit(op+0x10);
emit(lobyte(Result));
Cycles += 2;
return;
}
else {
emit(op+0x20);
eword(Result);
Cycles += 3;
return;
}
}
else {
error("Unknown Addressing Mode");
return;
}
}
/*
* do_indexed --- handle all wierd stuff for indexed addressing
*/
do_indexed(op)
int op;
{
eval();
if(!(*Optr++ == ',' && (*Optr == 'x' || *Optr == 'X')))
warn("Indexed Addressing Assumed");
if(Force_word){
if(op < 0x80 ){ /* group 2, no extended addressing */
emit(op+0x10); /* default to one byte indexed */
emit(lobyte(Result));
Cycles += 3;
return;
}
emit(op);
eword(Result);
Cycles += 4;
return;
}
Cycles += 3; /* assume 1 byte indexing */
if(Force_byte){
emit(op+0x10);
emit(lobyte(Result));
return;
}
if(Result==0){
emit(op+0x20);
Cycles--; /* ,x slightly faster */
return;
}
if(Result>0 && Result <=0xFF){
emit(op+0x10);
emit(lobyte(Result));
return;
}
if( op < 0x80 ){
warn("Value Truncated");
emit(op+0x10);
emit(lobyte(Result));
return;
}
emit(op);
eword(Result);
Cycles++; /* 2 byte slightly slower */
return;
}
SHAR_EOF
cat << \SHAR_EOF > DO9.C
/*
* MC6809 specific processing
*/
#define PAGE2 0x10
#define PAGE3 0x11
#define IPBYTE 0x9F /* extended indirect postbyte */
#define SWI 0x3F
/* register names */
#define RD 0
#define RX 1
#define RY 2
#define RU 3
#define RS 4
#define RPC 5
#define RA 8
#define RB 9
#define RCC 10
#define RDP 11
#define RPCR 12
/* convert tfr/exg reg number into psh/pul format */
int regs[] = { 6,16,32,64,64,128,0,0,2,4,1,8,0};
int rcycl[]= { 2,2, 2, 2, 2, 2, 0,0,1,1,1,1,0};
/* addressing modes */
#define IMMED 0 /* immediate */
#define IND 1 /* indexed */
#define INDIR 2 /* indirect */
#define OTHER 3 /* NOTA */
/*
* localinit --- machine specific initialization
*/
localinit()
{
}
/*
* do_op --- process mnemonic
*
* Called with the base opcode and it's class. Optr points to
* the beginning of the operand field.
*/
do_op(opcode,class)
int opcode; /* base opcode */
int class; /* mnemonic class */
{
int dist; /* relative branch distance */
int src,dst;/* source and destination registers */
int pbyte; /* postbyte value */
int amode; /* indicated addressing mode */
int j;
amode = set_mode(); /* pickup indicated addressing mode */
switch(class){
case INH: /* inherent addressing */
emit(opcode);
return;
case GEN: /* general addressing */
do_gen(opcode,amode);
return;
case IMM: /* immediate addressing */
if( amode != IMMED ){
error("Immediate Operand Required");
return;
}
Optr++;
eval();
emit(opcode);
emit(lobyte(Result));
return;
case REL: /* short relative branches */
eval();
dist = Result - (Pc+2);
emit(opcode);
if( (dist >127 || dist <-128) && Pass==2){
error("Branch out of Range");
emit(lobyte(-2));
return;
}
emit(lobyte(dist));
return;
case P2REL: /* long relative branches */
eval();
dist = Result - (Pc+4);
emit(PAGE2);
emit(opcode);
eword(dist);
return;
case P1REL: /* lbra and lbsr */
if( amode == IMMED)
Optr++; /* kludge for C compiler */
eval();
dist = Result - (Pc+3);
emit(opcode);
eword(dist);
return;
case NOIMM:
if( amode == IMMED ){
error("Immediate Addressing Illegal");
return;
}
do_gen(opcode,amode);
return;
case P2GEN:
emit(PAGE2);
if( amode == IMMED ){
emit(opcode);
Optr++;
eval();
eword(Result);
return;
}
do_gen(opcode,amode);
return;
case P3GEN:
emit(PAGE3);
if( amode == IMMED ){
emit(opcode);
Optr++;
eval();
eword(Result);
return;
}
do_gen(opcode,amode);
return;
case RTOR: /* tfr and exg */
emit(opcode);
src = regnum();
while(alpha(*Optr))Optr++;
if(src==ERR){
error("Register Name Required");
emit(0);
return;
}
if(*Optr++ != ','){
error("Missing ,");
emit(0);
return;
}
dst = regnum();
while(alpha(*Optr))Optr++;
if(dst==ERR){
error("Register Name Required");
emit(0);
return;
}
if( src==RPCR || dst==RPCR){
error("PCR illegal here");
emit(0);
return;
}
if( (src <=5 && dst >=8) ||
(src >=8 && dst <=5)){
error("Register Size Mismatch");
emit(0);
return;
}
emit( (src<<4)+dst );
return;
case INDEXED: /* indexed addressing only */
if( *Optr == '#'){
Optr++; /* kludge city */
amode = IND;
}
if( amode != IND ){
error("Indexed Addressing Required");
return;
}
do_indexed(opcode);
return;
case RLIST: /* pushes and pulls */
if(*Operand == EOS){
error("Register List Required");
return;
}
emit(opcode);
pbyte = 0;
do{
j = regnum();
if( j == ERR || j==RPCR)
error("Illegal Register Name");
else if(j==RS && (opcode==52))
error("Can't Push S on S");
else if(j==RU && (opcode==54))
error("Can't Push U on U");
else if(j==RS && (opcode==53))
error("Can't Pull S from S");
else if(j==RU && (opcode==55))
error("Can't Pull U from U");
else{
pbyte |= regs[j];
Cycles += rcycl[j];
}
while(*Optr != EOS && alpha(*Optr))Optr++;
}while( *Optr++ == ',' );
emit(lobyte(pbyte));
return;
case P2NOIMM:
if( amode == IMMED )
error("Immediate Addressing Illegal");
else{
emit(PAGE2);
do_gen(opcode,amode);
}
return;
case P2INH: /* Page 2 inherent */
emit(PAGE2);
emit(opcode);
return;
case P3INH: /* Page 3 inherent */
emit(PAGE3);
emit(opcode);
return;
case LONGIMM:
if( amode == IMMED ){
emit(opcode);
Optr++;
eval();
eword(Result);
}
else
do_gen(opcode,amode);
return;
case GRP2:
if( amode == IND ){
do_indexed(opcode+0x60);
return;
}
else if( amode == INDIR){
Optr++;
emit(opcode + 0x60);
emit(IPBYTE);
eval();
eword(Result);
Cycles += 7;
if(*Optr == ']'){
Optr++;
return;
}
error("Missing ']'");
return;
}
eval();
if(Force_word){
emit(opcode+0x70);
eword(Result);
Cycles += 3;
return;
}
if(Force_byte){
emit(opcode);
emit(lobyte(Result));
Cycles += 2;
return;
}
if(Result>=0 && Result <=0xFF){
emit(opcode);
emit(lobyte(Result));
Cycles += 2;
return;
}
else {
emit(opcode+0x70);
eword(Result);
Cycles += 3;
return;
}
case SYS: /* system call */
emit(SWI);
eval();
emit(lobyte(Result));
return;
default:
fatal("Error in Mnemonic table");
}
}
/*
* do_gen --- process general addressing mode stuff
*/
do_gen(op,mode)
int op;
int mode;
{
if( mode == IMMED){
Optr++;
emit(op);
eval();
emit(lobyte(Result));
return;
}
else if( mode == IND ){
do_indexed(op+0x20);
return;
}
else if( mode == INDIR){
Optr++;
emit(op+0x20);
emit(IPBYTE);
eval();
eword(Result);
Cycles += 7;
if(*Optr == ']'){
Optr++;
return;
}
error("Missing ']'");
return;
}
else if( mode == OTHER){
eval();
if(Force_word){
emit(op+0x30);
eword(Result);
Cycles += 3;
return;
}
if(Force_byte){
emit(op+0x10);
emit(lobyte(Result));
Cycles += 2;
return;
}
if(Result>=0 && Result <=0xFF){
emit(op+0x10);
emit(lobyte(Result));
Cycles += 2;
return;
}
else {
emit(op+0x30);
eword(Result);
Cycles += 3;
return;
}
}
else {
error("Unknown Addressing Mode");
return;
}
}
/*
* do_indexed --- handle all wierd stuff for indexed addressing
*/
do_indexed(op)
int op;
{
int pbyte;
int j,k;
int predec,pstinc;
Cycles += 2; /* indexed is always 2+ base cycle count */
predec=0;
pstinc=0;
pbyte=128;
emit(op);
if(*Optr=='['){
pbyte |= 0x10; /* set indirect bit */
Optr++;
if( !any((char)']',Optr))
error("Missing ']'");
Cycles += 3; /* indirection takes this much longer */
}
j=regnum();
if(j==RA){
Cycles++;
abd_index(pbyte+6);
return;
}
if(j==RB){
Cycles++;
abd_index(pbyte+5);
return;
}
if(j==RD){
Cycles += 4;
abd_index(pbyte+11);
return;
}
eval();
Optr++;
while(*Optr=='-'){
predec++;
Optr++;
}
j=regnum();
while( alpha(*Optr) )Optr++;
while(*Optr=='+'){
pstinc++;
Optr++;
}
if(j==RPC || j==RPCR){
if( pstinc || predec ){
error("Auto Inc/Dec Illegal on PC");
return;
}
if(j==RPC){
if(Force_word){
emit(pbyte+13);
eword(Result);
Cycles += 5;
return;
}
if(Force_byte){
emit(pbyte+12);
emit(lobyte(Result));
Cycles++;
return;
}
if(Result>=-128 && Result <=127){
emit(pbyte+12);
emit(lobyte(Result));
Cycles++;
return;
}
else {
emit(pbyte+13);
eword(Result);
Cycles += 5;
return;
}
}
/* PCR addressing */
if(Force_word){
emit(pbyte+13);
eword(Result-(Pc+2));
Cycles += 5;
return;
}
if(Force_byte){
emit(pbyte+12);
emit(lobyte(Result-(Pc+1)));
Cycles++;
return;
}
k=Result-(Pc+2);
if( k >= -128 && k <= 127){
emit(pbyte+12);
emit(lobyte(Result-(Pc+1)));
Cycles++;
return;
}
else{
emit(pbyte+13);
eword(Result-(Pc+2));
Cycles += 5;
return;
}
}
if(predec || pstinc){
if(Result != 0){
error("Offset must be Zero");
return;
}
if(predec>2 || pstinc>2){
error("Auto Inc/Dec by 1 or 2 only");
return;
}
if((predec==1 && (pbyte&0x10) != 0) ||
(pstinc==1 && (pbyte&0x10) != 0)){
error("No Auto Inc/Dec by 1 for Indirect");
return;
}
if(predec && pstinc){
error("Can't do both!");
return;
}
if(predec)
pbyte += predec+1;
if(pstinc)
pbyte += pstinc-1;
pbyte += rtype(j);
emit(pbyte);
Cycles += 1 + predec + pstinc;
return;
}
pbyte += rtype(j);
if(Force_word){
emit(pbyte+0x09);
eword(Result);
Cycles += 4;
return;
}
if(Force_byte){
emit(pbyte+0x08);
emit(lobyte(Result));
Cycles++;
return;
}
if(Result==0){
emit(pbyte+0x04);
return;
}
if((Result >= -16) && (Result <= 15) && ((pbyte&16)==0)){
pbyte &= 127;
pbyte += Result&31;
emit(pbyte);
Cycles++;
return;
}
if(Result >= -128 && Result <= 127){
emit(pbyte+0x08);
emit(lobyte(Result));
Cycles++;
return;
}
emit(pbyte+0x09);
eword(Result);
Cycles += 4;
return;
}
/*
* abd_index --- a,b or d indexed
*/
abd_index(pbyte)
int pbyte;
{
int k;
Optr += 2;
k=regnum();
pbyte += rtype(k);
emit(pbyte);
return;
}
/*
* rtype --- return register type in post-byte format
*/
rtype(r)
int r;
{
switch(r){
case RX: return(0x00);
case RY: return(0x20);
case RU: return(0x40);
case RS: return(0x60);
}
error("Illegal Register for Indexed");
return(0);
}
/*
* set_mode --- determine addressing mode from operand field
*/
set_mode()
{
register char *p;
if( *Operand == '#' )
return(IMMED); /* immediate addressing */
p = Operand;
while( *p != EOS && *p != BLANK && *p != TAB){/* any , before break */
if( *p == ',')
return(IND); /* indexed addressing */
p++;
}
if( *Operand == '[')
return(INDIR); /* indirect addressing */
return(OTHER); /* NOTA */
}
/*
* regnum --- return register number of *Optr
*/
regnum()
{
if( head(Optr,"D" ))return(RD);
if( head(Optr,"d" ))return(RD);
if( head(Optr,"X" ))return(RX);
if( head(Optr,"x" ))return(RX);
if( head(Optr,"Y" ))return(RY);
if( head(Optr,"y" ))return(RY);
if( head(Optr,"U" ))return(RU);
if( head(Optr,"u" ))return(RU);
if( head(Optr,"S" ))return(RS);
if( head(Optr,"s" ))return(RS);
if( head(Optr,"PC" ))return(RPC);
if( head(Optr,"pc" ))return(RPC);
if( head(Optr,"PCR" ))return(RPCR);
if( head(Optr,"pcr" ))return(RPCR);
if( head(Optr,"A" ))return(RA);
if( head(Optr,"a" ))return(RA);
if( head(Optr,"B" ))return(RB);
if( head(Optr,"b" ))return(RB);
if( head(Optr,"CC" ))return(RCC);
if( head(Optr,"cc" ))return(RCC);
if( head(Optr,"DP" ))return(RDP);
if( head(Optr,"dp" ))return(RDP);
return(ERR);
}
SHAR_EOF
cat << \SHAR_EOF > FFWD.C
/*
* file I/O version of forward ref handler
*/
#define FILEMODE 0644 /* file creat mode */
#define UPDATE 2 /* file open mode */
#define ABS 0 /* absolute seek */
int Forward =0; /* temp file's file descriptor */
char Fwd_name[] = { "Fwd_refs" } ;
/*
* fwdinit --- initialize forward ref file
*/
fwdinit()
{
Forward = creat(Fwd_name,FILEMODE);
if(Forward <0)
fatal("Can't create temp file");
close(Forward); /* close and reopen for reads and writes */
Forward = open(Fwd_name,UPDATE);
if(Forward <0)
fatal("Forward ref file has gone.");
#ifndef DEBUG
unlink(Fwd_name);
#endif
}
/*
* fwdreinit --- reinitialize forward ref file
*/
fwdreinit()
{
F_ref = 0;
Ffn = 0;
lseek(Forward,0L,ABS); /* rewind forward refs */
read(Forward,&Ffn,sizeof(Ffn));
read(Forward,&F_ref,sizeof(F_ref)); /* read first forward ref into mem */
#ifdef DEBUG
printf("First fwd ref: %d,%d\n",Ffn,F_ref);
#endif
}
/*
* fwdmark --- mark current file/line as containing a forward ref
*/
fwdmark()
{
write(Forward,&Cfn,sizeof(Cfn));
write(Forward,&Line_num,sizeof(Line_num));
}
/*
* fwdnext --- get next forward ref
*/
fwdnext()
{
int stat;
stat = read(Forward,&Ffn,sizeof(Ffn));
#ifdef DEBUG
printf("Ffn stat=%d ",stat);
#endif
stat = read(Forward,&F_ref,sizeof(F_ref));
#ifdef DEBUG
printf("F_ref stat=%d ",stat);
#endif
if( stat < 2 ){
F_ref=0;Ffn=0;
}
#ifdef DEBUG
printf("Next Fwd ref: %d,%d\n",Ffn,F_ref);
#endif
}
SHAR_EOF
cat << \SHAR_EOF > OUTPUT.C
/*
* stable --- prints the symbol table in alphabetical order
*/
stable(ptr)
struct nlist *ptr;
{
if (ptr != NULL)
{
stable (ptr->Lnext);
printf ("%-10s %04x\n",ptr->name,ptr->def);
stable (ptr->Rnext);
}
}
/*
* cross -- prints the cross reference table
*/
cross(point)
struct nlist *point;
{
struct link *tp;
int i = 1;
if (point != NULL)
{
cross (point->Lnext);
printf ("%-10s %04x *",point->name,point->def);
tp = point->L_list;
while (tp != NULL)
{
if (i++>10)
{
i=1;
printf("\n ");
}
printf ("%04d ",tp->L_num);
tp = tp->next;
}
printf ("\n");
cross (point->Rnext);
}
}
SHAR_EOF
cat << \SHAR_EOF > PSEUDO.C
/*
* pseudo --- pseudo op processing
*/
#define RMB 0 /* Reserve Memory Bytes */
#define FCB 1 /* Form Constant Bytes */
#define FDB 2 /* Form Double Bytes (words) */
#define FCC 3 /* Form Constant Characters */
#define ORG 4 /* Origin */
#define EQU 5 /* Equate */
#define ZMB 6 /* Zero memory bytes */
#define FILL 7 /* block fill constant bytes */
#define OPT 8 /* assembler option */
#define NULL_OP 9 /* null pseudo op */
#define PAGE 10 /* new page */
struct oper pseudo[] = {
"bsz", PSEUDO, ZMB, 0,
"end", PSEUDO, NULL_OP,0,
"equ", PSEUDO, EQU, 0,
"fcb", PSEUDO, FCB, 0,
"fcc", PSEUDO, FCC, 0,
"fdb", PSEUDO, FDB, 0,
"fill", PSEUDO, FILL, 0,
"nam", PSEUDO, NULL_OP,0,
"name", PSEUDO, NULL_OP,0,
"opt", PSEUDO, OPT, 0,
"org", PSEUDO, ORG, 0,
"pag", PSEUDO, PAGE, 0,
"page", PSEUDO, PAGE, 0,
"rmb", PSEUDO, RMB, 0,
"spc", PSEUDO, NULL_OP,0,
"ttl", PSEUDO, NULL_OP,0,
"zmb", PSEUDO, ZMB, 0
};
/*
* do_pseudo --- do pseudo op processing
*/
do_pseudo(op)
int op; /* which op */
{
char fccdelim;
int j;
int fill;
char *skip_white();
if( op != EQU && *Label )
install(Label,Pc);
P_force++;
switch(op){
case RMB: /* reserve memory bytes */
if( eval() ){
Pc += Result;
f_record(); /* flush out bytes */
}
else
error("Undefined Operand during Pass One");
break;
case ZMB: /* zero memory bytes */
if( eval() )
while( Result-- )
emit(0);
else
error("Undefined Operand during Pass One");
break;
case FILL: /* fill memory with constant */
eval();
fill = Result;
if( *Optr++ != ',' )
error("Bad fill");
else{
Optr = skip_white(Optr);
eval();
while( Result-- )
emit(fill);
}
break;
case FCB: /* form constant byte(s) */
do{
Optr = skip_white(Optr);
eval();
if( Result > 0xFF ){
if(!Force_byte)
warn("Value truncated");
Result = lobyte(Result);
}
emit(Result);
}while( *Optr++ == ',' );
break;
case FDB: /* form double byte(s) */
do{
Optr = skip_white(Optr);
eval();
eword(Result);
}while( *Optr++ == ',' );
break;
case FCC: /* form constant characters */
if(*Operand==EOS)
break;
fccdelim = *Optr++;
while( *Optr != EOS && *Optr != fccdelim)
emit(*Optr++);
if(*Optr == fccdelim)
Optr++;
else
error("Missing Delimiter");
break;
case ORG: /* origin */
if( eval() ){
Old_pc = Pc = Result;
f_record(); /* flush out any bytes */
}
else
error("Undefined Operand during Pass One");
break;
case EQU: /* equate */
if(*Label==EOS){
error("EQU requires label");
break;
}
if( eval() ){
install(Label,Result);
Old_pc = Result; /* override normal */
}
else
error("Undefined Operand during Pass One");
break;
case OPT: /* assembler option */
P_force=0;
if( head(Operand,"l") )
Lflag=1;
else if( head(Operand,"nol"))
Lflag=0;
else if( head(Operand,"c")){
Cflag=1;
Ctotal=0;
}
else if( head(Operand,"noc"))
Cflag=0;
else if( head(Operand,"contc")){
Cflag=1;
}
else if ( head(Operand,"s"))
Sflag = 1;
else if ( head(Operand,"cre"))
CREflag = 1;
else
error("Unrecognized OPT");
break;
case PAGE: /* go to a new page */
P_force=0;
N_page = 1;
if (Pass == 2 )
if (Lflag)
{
printf ("\f");
printf ("%-10s",Argv[Cfn]);
printf (" ");
printf ("page %3d\n",Page_num++);
}
break;
case NULL_OP: /* ignored psuedo ops */
P_force=0;
break;
default:
fatal("Pseudo error");
}
}
SHAR_EOF
# End of shell archive
exit 0
--
Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page
Have five nice days.